package com.stwyj.sbd.config;

import com.stwyj.sbd.common.property.AppTestProperties;
import com.stwyj.sbd.config.exception.BasicErrorAttributes;
import com.stwyj.sbd.config.validator.BeanValidator;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.boot.web.servlet.error.ErrorAttributes;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.config.EnableMongoAuditing;
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
import org.springframework.data.repository.query.QueryLookupStrategy;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.validation.SmartValidator;
import org.springframework.web.client.RestTemplate;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.time.Duration;
import java.util.Objects;
import java.util.concurrent.ThreadPoolExecutor;

/**
 *<p>
 * 应用配置类
 *</p>
 *
 * @author stwyj
 * @since 2018/11/30
 */
@Configuration
@Slf4j
@EnableConfigurationProperties(AppTestProperties.class)
@EnableMongoAuditing
@EnableMongoRepositories(basePackages = {"com.stwyj.sbd.dao.repository"},queryLookupStrategy = QueryLookupStrategy.Key.CREATE_IF_NOT_FOUND)
public class AppConfig {

    @Resource
    AppTestProperties appTestProperties;

    @PostConstruct
    public void init() {
        log.info("测试自动配置：{}", Objects.toString(appTestProperties, "配置不存在"));
    }

    /**
     * http请求工具类
     *
     * @return 工具类
     */
    @Bean
    public RestTemplate restTemplate() {
        RestTemplateBuilder builder = new RestTemplateBuilder();

        // 此处可通过builder设置连接属性配置，例如设置连接超时时间
        builder.setConnectTimeout(Duration.ofSeconds(10L));

        // 基于httpclient
        ClientHttpRequestInterceptor interceptor = (request, body, execution) -> {
            log.debug(request.getURI().toString());
            return execution.execute(request, body);
        };

        return builder.interceptors(interceptor).build();
    }

    /**
     * 参数验证bean
     * @param smartValidator 默认校验
     * @return 参数校验实例
     */
    @Bean
    public BeanValidator beanValidator(SmartValidator smartValidator) {
        return new BeanValidator(smartValidator);
    }

    /**
     * 基础错误异常
     * @return
     */
    @Bean
    public ErrorAttributes errorAttributes() {
        return new BasicErrorAttributes();
    }

    @Bean(name = "asyncHttpExecutor", initMethod = "initialize", destroyMethod = "destroy")
    public ThreadPoolTaskExecutor asyncHttpExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        // 线程名队列
        executor.setThreadNamePrefix("AsyncHttpExecutorThread-");
        // 核心线程数
        executor.setCorePoolSize(10);
        // 最大线程数
        executor.setMaxPoolSize(50);
        // 阻塞任务队列容量
        executor.setQueueCapacity(200);
        // 任务拒绝处理器 (AbortPolicy 丢弃任务，抛运行时异常RejectedExecutionException - CallerRunsPolicy 执行任务 - DiscardPolicy 忽视，什么都不会发生 - DiscardOldestPolicy 从队列中踢出最先进入队列的任务)
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardOldestPolicy());
        return executor;
    }
}
